﻿using System;
#if WINDOWS_PHONE
using StyleMVVM.Data.Collections;
#else
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Utilities;
#if !DOT_NET
using Windows.Foundation;

#endif

namespace StyleMVVM.Logging
{
	internal class HoldQueueLog : ILog
	{
		private readonly object lockObject = new object();
		private readonly HoldingQueueAdapter adapter = new HoldingQueueAdapter();
		private ILog realLog;
		private Action<ConcurrentQueue<LogEntry>> bootstrapperReady;

		public HoldQueueLog(Action<ConcurrentQueue<LogEntry>> bootstrapperReady)
		{
			this.bootstrapperReady = bootstrapperReady;
		}

#if NETFX_CORE
		public IAsyncOperation<bool> Configure()
		{
			return AsyncHelper.ReturnAsyncOp(true);
		}
#else

		public Task<bool> Configure()
		{
			return TaskHelper.ReturnTask(true);
		}

#endif

		public LogLevel LoggingLevel
		{
			get { return LogLevel.DEBUG; }
			set { }
		}

		public ILog RealLog
		{
			get { return realLog; }
			set { realLog = value; }
		}

		public void Flush()
		{
			throw new NotImplementedException();
		}

		public void Debug(string message)
		{
			throw new NotImplementedException();
		}

		public void Debug(string message, string supplemental)
		{
			throw new NotImplementedException();
		}

		public void Debug(string message, string supplemental = null, Exception exp = null)
		{
			Log(
				new LogEntry
					{
						Level = LogLevel.FATAL,
						Message = message,
						Supplemental = supplemental,
						Exception = exp
					});
		}

		public void Info(string message)
		{
			throw new NotImplementedException();
		}

		public void Info(string message, string supplemental)
		{
			throw new NotImplementedException();
		}

		public void Info(string message, string supplemental = null, Exception exp = null)
		{
			Log(
				new LogEntry
					{
						Level = LogLevel.FATAL,
						Message = message,
						Supplemental = supplemental,
						Exception = exp
					});
		}

		public void Warn(string message)
		{
			throw new NotImplementedException();
		}

		public void Warn(string message, string supplemental)
		{
			throw new NotImplementedException();
		}

		public void Warn(string message, string supplemental = null, Exception exp = null)
		{
			Log(
				new LogEntry
					{
						Level = LogLevel.FATAL,
						Message = message,
						Supplemental = supplemental,
						Exception = exp
					});
		}

		public void Error(string message)
		{
			throw new NotImplementedException();
		}

		public void Error(string message, string supplemental)
		{
			throw new NotImplementedException();
		}

		public void Error(string message, string supplemental = null, Exception exp = null)
		{
			Log(
				new LogEntry
					{
						Level = LogLevel.FATAL,
						Message = message,
						Supplemental = supplemental,
						Exception = exp
					});
		}

		public void Fatal(string message)
		{
			throw new NotImplementedException();
		}

		public void Fatal(string message, string supplemental)
		{
			throw new NotImplementedException();
		}

		public void Fatal(string message, string supplemental = null, Exception exp = null)
		{
			Log(
				new LogEntry
					{
						Level = LogLevel.FATAL,
						Message = message,
						Supplemental = supplemental,
						Exception = exp
					});
		}

		public void Log(LogEntry logEntry)
		{
			if (RealLog != null)
			{
				RealLog.Log(logEntry);
			}
			else
			{
				adapter.Log(logEntry);

				if (bootstrapperReady != null && Bootstrapper.InstanceIsReady)
				{
					Action<ConcurrentQueue<LogEntry>> tempReady;

					lock (lockObject)
					{
						tempReady = bootstrapperReady;
						bootstrapperReady = null;
					}

					if (tempReady != null)
					{
						tempReady(adapter.PendingMessages);
					}
				}
			}
		}
	}
}